home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Scene 96
/
Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso
/
misc
/
coding
/
vesacode
/
vesa.asm
< prev
next >
Wrap
Assembly Source File
|
1996-02-13
|
29KB
|
919 lines
; =========================================================
; = VESA - Intro =
; = =
; = coded by zan in jan '96 =
; =========================================================
.model tiny
.386
locals
.code
org 100h
; ---------------------------------------------------------
; Konstanten
; ---------------------------------------------------------
stars equ 300
centerx equ 320
centery equ 240
centerxy equ centerx shl 16+centery
distancez equ 200
weiss equ 255
digitalxsize equ 10
digitalysize equ 10
digitalspace equ 5
; ---------------------------------------------------------
; Hauptprogramm
; ---------------------------------------------------------
begin:
cld ; go ahead, fred
call cleardata ; COM-Datei wurde verkürzt, deshalb
; ist der Datenbereich in einem
; undefiniertem Zustand
call check386 ; min. 386er
jc ende
call savepalette ; Palette retten
mov si,offset originalpalette ; ausfaden
call fadeout
call initmode ; VESA-Mode 101h testen
jc ende
call initdata ; Tabellen usw. initialisieren
call palblack ; Palette schwarz
call fillscreen ; Hintergrund aufbauen
mov ecx,190 shl 16+(centery-3*digitalysize)
mov dx,64 ; Telefonnummern Teil 1
mov si,offset phonedigital1
call digitaltext
mov ecx,190 shl 16+(centery+digitalysize)
mov si,offset phonedigital2 ; Telefonnummern Teil 2
call digitaltext
mov si,offset newpalette ; einfaden
call fadein
@@angle:
call showpoints ; 3D-Feld anzeigen
inc anglex ; Winkel verändern
inc angley
inc anglez
mov ah,1 ; Tastaturstatus auslesen
int 16h
jnz @@raus ; Taste gedrückt ?
call retrace ; Retrace abwarten
jmp short @@angle ; nächstes Bild
@@raus:
xor ah,ah ; Tastaturpuffer leeren
int 16h
mov si,offset newpalette
call fadeout ; ausfaden
mov ax,3 ; in Textmodus schalten
int 10h
call palblack ; Palette vorsichtshalber schwarz
ende:
mov ah,9 ; Telefonnummern anzeigen
mov dx,offset phonenumbers
int 21h
mov si,offset originalpalette ; einfaden
call fadein
mov ah,4Ch ; Shutdown
int 21h
; ---------------------------------------------------------
; CLEARDATA: füllt Datenbereich mit Nullen
; ---------------------------------------------------------
cleardata proc near
push bx
mov bx,offset endofzeros+1 ; Endelabel
sub bx,offset startofzeros ; Startlabel
@@data2zero:
mov byte ptr startofzeros[bx],0; mit 0 überschreiben
dec bx ; nächstes Byte
jnz @@data2zero ; fertig ?
pop bx
ret
cleardata endp
; ---------------------------------------------------------
; CHECK386: testet auf 386 bzw. Nachfolger
; ---------------------------------------------------------
check386 proc near
push ax
xor ax,ax ; 0000hex pushen
push ax
popf ; als Flags laden
pushf ; und wieder sichern
pop ax ; in AX
and ax,0F000h ; nur Bits 12 bis 15 interessant
cmp ax,0F000h ; alle gesetzt ?
je @@error ; ist 8086/8088/V20/V30
mov ax,7000h ; 7000hex pushen
push ax
popf ; als Flags laden
pushf ; und wieder sichern
pop ax ; als AX wiederholen
and ah,70h ; überprüfen
jz @@error ; nicht verändert => ist 286
clc
jmp short @@raus ; Bereinigungcode ausführen
@@error:
mov ah,9 ; god bless u
mov dx,offset cpu386
int 21h
stc
@@raus:
pop ax
ret
check386 endp
; ---------------------------------------------------------
; INITMODE: initialisiert Mode 101h
; ---------------------------------------------------------
initmode proc near
pushad
push cs ; auf VESA-Treiber prüfen
pop es ; Segment der Tabelle laden
mov di,offset infoblock ; Offset laden
mov ax,4F00h ; Info-Unterfunktion
int 10h ; Interrupt aufrufen
cmp ax,004Fh ; VESA vorhanden ? Test 1
jne @@error
cmp dword ptr infoblock[0],'ASEV'
jne @@error ; VESA vorhanden ? Test 2
mov ax,4F01h ; Modus 101h unterstützt ?
mov cx,101h
int 10h
cmp ax,004Fh
jne @@error
mov eax,dword ptr infoblock[0Ch]
or eax,eax
jz @@error
mov vesaptr,eax ; FAR-CALL Zeiger
mov ax,word ptr infoblock[4] ; Granularität auf 64k testen
cmp ax,64
jne @@error
mov ax,4F02h ; Modus einstellen
mov bx,101h
int 10h
clc
jmp short @@raus
@@error:
mov ah,9 ; omigod
mov dx,offset problem
int 21h
stc
@@raus:
popad
ret
initmode endp
; ---------------------------------------------------------
; INITDATA: initialisiert alle Tabellen
; ---------------------------------------------------------
initdata proc near
pushad
xor ecx,ecx ; bei Y=0 anfangen
@@calc_yoffset:
imul eax,ecx,640 ; Offset berechnen
mov yoffset[bx],eax ; und sichern
add bx,4 ; ist DWord = 4 Bytes
inc cx ; nächste Zeile
cmp cx,479 ; fertig ?
jna @@calc_yoffset
xor bx,bx ; Laufindex, bei 0 anfangen
@@randomize:
call random ; Zufallsgenerator
sar ah,1 ; auf -63..+63 beschränken
mov pointxtab[bx],ah ; und sichern
call random ; Zufallsgenerator
sar ah,1 ; auf -63..+63 beschränken
mov pointytab[bx],ah ; und sichern
call random ; Zufallsgenerator
sar ah,1 ; auf -63..+63 beschränken
mov pointztab[bx],ah ; und sichern
inc bx ; nächster Punkt
cmp bx,stars ; fertig ?
jne @@randomize
xor bx,bx ; wieder Laufindex
@@calc_cosinus:
mov si,63 ; Cosinus aus Sinus aufbauen
sub si,bx ; 1.Quadrant Cosinus umgekehrt Sinus
mov al,sinustab[si]
mov cosinustab[bx],al
neg al ; 256-Cosinus
mov cosinus_3[bx],al ; 3.Quadrant
mov al,sinustab[bx] ; Sinuswert laden
mov cosinus_4[bx],al ; 4.Quadrant Cosinus
neg al ; 256-Sinus
mov cosinus_2[bx],al ; 2.Quadrant
inc bl ; nächster Winkel
cmp bl,64 ; fertig ?
jne @@calc_cosinus
xor bx,bx ; Palette aufbauen
xor cl,cl
@@palette_loop1:
mov newpalette[bx+2],cl ; nur blau
inc cl
add bl,3
cmp cl,64
jne @@palette_loop1
mov word ptr newpalette[3*255],63 shl 8+63
; weiß
mov newpalette[3*255+2],63
mov ax,0A000h ; ES ist immer 0A000h
mov es,ax
popad
ret
initdata endp
; ---------------------------------------------------------
; SHOWPOINTS: zeichnet neues Bild
; ---------------------------------------------------------
showpoints proc near
pushad
xor bx,bx ; Laufindex Byte
xor bp,bp ; Laufindex DWord
@@loop:
mov dl,oldcolor[bx] ; alte Farbe holen
cmp dl,weiss ; doppelt gezeichnet ?
je @@doppelt
mov ecx,screen2d[bp] ; alten Koordinaten holen
call putpixel
@@doppelt:
mov al,pointxtab[bx] ; Urpsrungskoordinaten holen
mov ah,pointytab[bx]
mov cl,pointztab[bx]
movzx si,anglez ; um Z-Achse drehen
mov dl,sinustab[si]
mov dh,cosinustab[si]
call rotate
xchg ah,cl
movzx si,angley ; um Y-Achse drehen
mov dl,sinustab[si]
mov dh,cosinustab[si]
call rotate
xchg ah,cl
xchg al,cl
movzx si,anglex ; um X-Achse drehen
mov dl,sinustab[si]
mov dh,cosinustab[si]
call rotate
xchg al,cl
movsx dx,cl ; auf 2D umrechnen
movsx cx,al
shl ecx,16
movsx cx,ah
call conv3d
call setwindow
mov dl,weiss ; weißer Punkt
xchg es:[di],dl
mov oldcolor[bx],dl
mov screen2d[bp],ecx ; für Wiederherstellung XY sichern
add bp,4 ; Laufindexe anpassen
inc bx
cmp bx,stars ; fertig ?
jne @@loop
popad
ret
showpoints endp
; ---------------------------------------------------------
; CONV3D: konvertiert 3D-Koordinaten in 2D
; -> ECX X,Y
; -> DX Z
; <- ECX X,Y der 2D-Form
; ---------------------------------------------------------
conv3d proc near
push ax
push bx
push dx
push si
add dx,distancez-1 ; etwas Distanz zum Betrachter schaffen
or dx,dx ; Division durch 0 verhindern
js @@div0 ; negatives Z, nicht sichtbar
inc dx
mov si,dx ; Z sichern
mov ax,cx ; X holen
shr ecx,16
sal ax,8 ; anpassen
cwd ; DX mit Vorzeichen füllen
idiv si ; durch Z dividieren
mov bx,ax ; und sichern
mov ax,cx ; Y holen
sal ax,8 ; anpassen
cwd ; DX mit Vorzeichen füllen
idiv si ; durch Z dividieren
shrd ecx,eax,16 ; 2D-X in obere Hälfte von ECX
mov cx,bx ; 2D-Y holen
add ecx,centerxy ; zentrieren
jmp short @@nodiv0 ; Division-durch-0-Routine überspringen
@@div0: mov ecx,640 shl 16+480 ; irgendein nicht sichtbarer Punkt
@@nodiv0:
pop si
pop dx
pop bx
pop ax
ret
conv3d endp
; ---------------------------------------------------------
; ROTATE: rotiert um eine Achse
; -> AX X,Y bzw. Z (insgesamt 2 Werte)
; -> DL Sinus
; -> DH Cosinus
; <- AX neue X,Y bzw. Z
; ---------------------------------------------------------
rotate proc near
push cx
push bx
push ax
mov bx,ax ; Xneu = X*cos-Y*sin
imul dh
mov cx,ax
mov al,bh
imul dl
sub cx,ax
pop ax
imul dl ; Yneu = X*sin+Y*cos
xchg bx,ax
mov al,ah
imul dh
add ax,bx
sal cx,1 ; Xneu und Yneu runterrechnen, da
sal ax,1 ; Sinus und Cosinus -127..+127 statt
; -1..+1
mov al,ch
pop bx
pop cx
ret
rotate endp
; ---------------------------------------------------------
; SETWINDOW: setzt das Fenster im VRAM
; -> ECX X,Y
; <- DI Offset
; ---------------------------------------------------------
setwindow proc near
push ax
push bx
push ecx
push edx
mov di,cx ; y holen
shl di,2 ; auf DWORD ausrichten
mov edx,yoffset[di] ; entsprechender 32-Bit-Offset
shr ecx,16 ; x addieren
add edx,ecx
mov di,dx ; in Granularitätsoffset umrechnen
shr edx,16 ; Segmentanteil herausfiltern
cmp dx,vesaseg
je @@ok
mov vesaseg,dx
xor bx,bx
call dword ptr vesaptr ; Window setzen
@@ok:
pop edx
pop ecx
pop bx
pop ax
ret
setwindow endp
; ---------------------------------------------------------
; PUTPIXEL: setzt einen Punkt
; -> ECX X,Y
; -> DL Farbe
; ---------------------------------------------------------
putpixel proc near
cmp cx,479 ; Y vorzeichenlos über 479 ?
ja @@do_not_set_any_pixel
cmp ecx,640 shl 16 ; X vorzeichenlos über 639 ?
jae @@do_not_set_any_pixel
call setwindow ; Window setzen
mov es:[di],dl ; Punkt setzen
@@do_not_set_any_pixel:
ret
putpixel endp
; ---------------------------------------------------------
; XLINE: zeichnet eine horizontale Linie
; -> ECX X1,X2
; -> EDX Y,Farbe
; ---------------------------------------------------------
xline proc near
pushad
mov bl,dl ; Farbe sichern
shr edx,16 ; Y holen
mov bp,dx ; und sichern
mov dh,bl ; Farbe zurück
mov eax,ecx ; X1 holen
shr eax,16
mov bx,cx ; X2 holen
shrd ecx,eax,16 ; Startpunkt checken
mov cx,bp
call setwindow
cmp di,65535-640 ; Window-Break ?
jae @@window_break
sub bx,ax ; schnelle Variante
inc bx
mov cx,bx ; Anzahl Punkte in der Linie
mov al,dh ; Farbe
rep stosb ; ausgeben
jmp short @@raus
@@window_break:
shl ebx,16 ; langsame Variante
@@loop:
call setwindow ; (ähnlich PUTPIXEL)
mov es:[di],dh
add ecx,10000h ; nächstes X
cmp ecx,ebx ; fertig ?
jna @@loop
@@raus:
popad
ret
xline endp
; ---------------------------------------------------------
; YLINE: zeichnet eine vertikale Linie
; -> ECX Y1,Y2
; -> EDX X,Farbe
; ---------------------------------------------------------
yline proc near
pushad
mov bx,cx ; Y2 sichern
shr ecx,16
mov ax,cx ; Y1 sichern
mov ecx,edx ; X setzen
mov cx,ax ; Y1 setzen
@@loop:
call setwindow ; Window anpassen
mov es:[di],dl ; Punkt setzen
inc cx ; nächstes Y
cmp cx,bx ; fertig ?
jna @@loop
popad
ret
yline endp
; ---------------------------------------------------------
; FILLSCREEN: füllt den gesamten Bildschirm mit Farbverlauf
; ---------------------------------------------------------
fillscreen proc near
pusha
xor ax,ax
xor edx,edx ; Farbe und Y setzen
mov ecx,639 ; X1 und X2 setzen
@@loop1:
call xline ; Linie zeichnen
inc al ; Farbe ändern
and al,3
jnz @@dontinc1
inc dl
@@dontinc1:
add edx,10000h ; vorheriges Y
cmp edx,240 shl 16
jna @@loop1 ; fertig ?
@@loop2:
call xline ; Linie zeichnen
inc al ; Farbe ändern
and al,3
jnz @@dontinc2
dec dl
@@dontinc2:
add edx,10000h ; vorheriges Y
cmp edx,480 shl 16
jna @@loop2 ; fertig ?
popa
ret
fillscreen endp
; ---------------------------------------------------------
; DIGITALCHAR: zeichnet ein Zeichen in Digitalschrift
; -> ECX X,Y (obere linke Ecke)
; -> DH DIGITAL-Code
; -> DL Farbe
; ---------------------------------------------------------
digitalchar proc near
pushad
mov ebp,ecx ; Koordinaten sichern
mov ax,dx ; sichern
mov si,0 ; Laufindex
@@loop_xline:
test ah,1 ; unterstes Bit gelöscht ?
jz @@nix_xline
mov ecx,ebp ; Koordinaten holen
shr ecx,16 ; X1 und X2 berechnen
push cx
inc cx
shl ecx,16
pop cx
add cx,digitalxsize-1
imul dx,si,digitalysize ; Y berechnen
add dx,bp
shl edx,16
mov dl,al ; Farbe holen
call xline ; Linie zeichnen
dec cx ; Parallelen zeichnen
add ecx,10000h
sub edx,10000h
call xline
add edx,20000h
call xline
@@nix_xline:
shr ah,1 ; ein Bit weiterrücken
inc si
cmp si,2 ; XLINEs fertig ?
jna @@loop_xline
mov si,0 ; wieder Laufindex
@@loop_yline:
test ah,1 ; unterstes Bit testen
jz @@nix_yline
mov cx,bp ; Y1 und Y2 berechnen
inc cx
shl ecx,16
mov cx,bp
add cx,digitalxsize-1
imul dx,si,digitalysize ; X berechnen
mov edi,ebp
shr edi,16
add dx,di
shl edx,16
mov dl,al ; Farbe holen
call yline ; Linie zeichnen
dec cx ; Parallelen zeichnen
add ecx,10000h
sub edx,10000h
call yline
add edx,20000h
call yline
@@nix_yline:
shr ah,1 ; ein Bit weiterrücken
inc si
cmp si,2 ; 2.Y-Bit ?
jne @@noinc
add bp,digitalysize ; jups, Y anpassen
sub ebp,(2*digitalxsize) shl 16
@@noinc:
cmp si,3 ; fertig ?
jna @@loop_yline
popad
ret
digitalchar endp
; ---------------------------------------------------------
; DIGITALTEXT: zeichnet eine Zeichenkette in Digitalschrift
; -> ECX X,Y
; -> DL Farbe
; -> SI Offset des Textes
; ---------------------------------------------------------
digitaltext proc near
pushad
@@loop:
mov dh,[si] ; ein Zeichen holen
cmp dh,'$' ; fertig ?
je @@fertig
call digitalchar ; Zeichen ausgeben
inc si ; eins weiterrücken
add ecx,(digitalxsize+digitalspace) shl 16
jmp short @@loop ; X anpassen, nächstes Zeichen
@@fertig:
popad
ret
digitaltext endp
; ---------------------------------------------------------
; SAVEPALETTE: rettet die Originalpalette
; ---------------------------------------------------------
savepalette proc near
pusha
xor al,al
mov dx,3C7h ; Read-Adress auf Farbe 0
out dx,al
add dl,2 ; auf Data-Port weiter
mov cx,3*256 ; 3*256 Farben
mov di,offset originalpalette ; Tabelle bei CS:DI
segcs rep insb ; los geht's
popa
ret
savepalette endp
; ---------------------------------------------------------
; SETPALETTE: setzt eine temporäre Palette
; ---------------------------------------------------------
setpalette proc near
pusha
xor al,al ; bei Farbe 0 anfangen
mov dx,3C8h
out dx,al
inc dx
mov cx,3*256 ; 3*256 Farben
mov si,offset temppalette ; Zeiger auf Tabelle
segcs rep outsb ; und setzen
popa
ret
setpalette endp
; ---------------------------------------------------------
; PALBLACK: setzt die komplette Palette auf schwarz
; ---------------------------------------------------------
palblack proc near
pusha
xor al,al ; bei Farbe 0 anfangen
mov dx,3C8h
out dx,al
inc dx ; auf Datenport
mov cx,3*256 ; 768 Farbwerte
@@loop:
out dx,al ; ausgeben
loop @@loop
popa
ret
palblack endp
; ---------------------------------------------------------
; FADEIN: sanftes Einfaden der Palette
; -> SI Offset der Tabelle
; ---------------------------------------------------------
fadein proc near
pusha
xor cl,cl ; 64 Abstufungen
@@frame_loop:
xor bx,bx ; 3*256 Farben
@@color_loop:
movzx ax,[bx+si] ; Farbwert holen
mul cl ; neu = alt*Stufe/64
shr ax,6
mov temppalette[bx],al
inc bx ; nächste Farbe
cmp bx,3*256 ; fertig ?
jne @@color_loop
call retrace ; synchronisieren
call setpalette ; ausgeben
inc cl ; nächste Stufe
cmp cl,64
jna @@frame_loop
popa
ret
fadein endp
; ---------------------------------------------------------
; FADEOUT: sanftes Ausfaden der Palette
; -> SI Offset der Tabelle
; ---------------------------------------------------------
fadeout proc near
pusha
mov cl,64 ; 64 Abstufungen
@@frame_loop:
xor bx,bx ; 3*256 Farben
@@color_loop:
movzx ax,[bx+si] ; Farbwert holen
mul cl ; neu = alt*Stufe/64
shr ax,6
mov temppalette[bx],al
inc bx ; nächste Farbe
cmp bx,3*256 ; fertig ?
jne @@color_loop
call retrace ; synchronisieren
call setpalette ; setzen
dec cl ; nächste Stufe
jnz @@frame_loop
popa
ret
fadeout endp
; ---------------------------------------------------------
; RETRACE: wartet auf den vertikalen Retrace
; ---------------------------------------------------------
retrace proc near
pusha
mov dx,3DAh ; Portadresse
@@warte:
in al,dx ; Status lesen
and al,8 ; nur Bit 4 interessant
jz @@warte ; wenn 0, dann warten
popa
retrace endp
; ---------------------------------------------------------
; RANDOM: liefert eine WORD-Zufallszahl zurück
; <- AX
; ---------------------------------------------------------
random proc near
push dx
imul ax,randomseed,8405h ; 16-Bit-Algorithmus
inc ax ; bißchen zufälliger
mov randomseed,ax ; Startwert ändern
pop dx
ret
random endp
; ---------------------------------------------------------
; Daten
; ---------------------------------------------------------
problem db 'Advanced VESA-videomode 101h not supported by your system.',10,13
db 'Just run a VESA-driver such as UNIVBE (especially Cirrus-Logic-cards).',10,13,'$'
cpu386 db 'Sorry, you need at least a 386.',10,13,'$'
phonenumbers db 'This source is available at Ghost BBS.',9,9,9
db 'VESA iNTRO done by zÅ∩',10,13
db ' call now +49-30-99400897',10,13
db ' or +49-30-99400898',10,13,'$'
phonedigital1 db 00101101b,01111011b,00101100b,00101100b,0 ; CALL
db 01111101b,01010111b,01111101b,00000010b ; 030-
db 01011111b,01011111b,01011010b,01111101b ; 9940
db 01111101b,01111111b,01011111b,01010001b ; 0897
db '$'
phonedigital2 db 0,01100110b,00100010b,0 ; or
db 01111101b,01010111b,01111101b,00000010b ; 030-
db 01011111b,01011111b,01011010b,01111101b ; 9940
db 01111101b,01111111b,01011111b,01111111b ; 0898
db '$'
randomseed dw 286Ah
sinustab db 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47
db 50, 53, 56, 58, 61, 64, 67, 69, 72, 74, 77, 79, 82, 84, 86, 89
db 91, 93, 95, 97, 99,101,103,105,106,108,110,111,113,114,115,117
db 118,119,120,121,122,123,124,124,125,125,126,126,127,127,127,127
startofzeros label byte
cosinustab db 64 dup (0)
cosinus_2 db 64 dup (0)
cosinus_3 db 64 dup (0)
cosinus_4 db 64 dup (0)
infoblock db 262 dup (0)
vesaptr dd 0
vesaseg dw 0
anglex db 0
angley db 0
anglez db 0
pointxtab db stars dup (0)
pointytab db stars dup (0)
pointztab db stars dup (0)
screen2d dd stars dup (0)
oldcolor db stars dup (0)
newpalette db 3*256 dup (0)
originalpalette db 3*256 dup (0)
temppalette db 3*256 dup (0)
yoffset dd 480 dup (0)
endofzeros label byte
end begin